#include "video_stream.h"
#include "listener.h"

template<> std::set<Stream::Video::Listener::Interface*>
        Base::Listener::Interface<Stream::Video::Listener::Interface>::listener_ =
        std::set<Stream::Video::Listener::Interface*>();

using namespace xcast;

class VideoStreamListener : public Base::Listener::Interface<Stream::Video::Listener::Interface> {
public:
  static void OnAdd(const char* stream_id, bool up, uint64_t uin, bool add) {
    for (auto it : listener_) {
      if (up) {
        it->OnUpVideoStream(stream_id, add);
      } else {
        it->OnDownVideoStream(stream_id, uin, add);
      }
    }
  }
  
  static void OnUpdate(const char* stream_id, uint64_t uin, int state) {
    for (auto it : listener_) {
      it->OnVideoStreamUpdate(stream_id, uin, state);
    }
  }

  static void OnVideoFrame(uint64_t uin, uint8_t* data, uint32_t data_size, int32_t format, uint32_t width, uint32_t height, uint32_t rotate, const char* stream) {
    for (auto it : listener_) {
      it->OnVideoStreamFrame(uin, data, data_size, format, width, height, rotate, stream);
    }
  }

  static void OnVideoLayer(
    uint32_t layer_index, uint32_t layer_size, uint8_t* layer_data, uint32_t layer_format, uint32_t layer_blend_mode,
    double layer_left, double layer_top, uint32_t layer_width, uint32_t layer_height, uint32_t layer_container_width, uint32_t layer_container_height,
    uint64_t layer_uin, bool layer_visible, const char* layer_stream) {
    for (auto it : listener_) {
      it->OnVideoStreamLayer(
        layer_index, layer_size, layer_data, layer_format, layer_blend_mode,
        layer_left, layer_top, layer_width, layer_height, layer_container_width, layer_container_height,
        layer_uin, layer_visible, layer_stream);
    }
  }
};

namespace Stream {
namespace Video {
namespace Listener {
void Add(Interface* listener) {
  VideoStreamListener::Add(listener);
}

void Remove(Interface* listener) {
  VideoStreamListener::Remove(listener);
}
}

namespace XcastEvent {
  void OnAdd(const char* stream_id, bool up, uint64_t uin, bool add) {
    VideoStreamListener::OnAdd(stream_id, up, uin, add);
  }
  
  void OnUpdate(const char* stream_id, uint64_t uin, int state){
    VideoStreamListener::OnUpdate(stream_id, uin, state);
  }

  void OnVideoFrame(uint64_t uin, uint8_t* data, uint32_t data_size, int32_t format, uint32_t width, uint32_t height, uint32_t rotate, const char* stream) {
    VideoStreamListener::OnVideoFrame(uin, data, data_size, format, width, height, rotate, stream);
  }

  void OnVideoLayer(
    uint32_t layer_index, uint32_t layer_size, uint8_t* layer_data, uint32_t layer_format, uint32_t layer_blend_mode,
    double layer_left, double layer_top, uint32_t layer_width, uint32_t layer_height, uint32_t layer_container_width, uint32_t layer_container_height,
    uint64_t layer_uin, bool layer_visible, const char* layer_stream) {
    VideoStreamListener::OnVideoLayer(
      layer_index, layer_size, layer_data, layer_format, layer_blend_mode,
      layer_left, layer_top, layer_width, layer_height, layer_container_width, layer_container_height,
      layer_uin, layer_visible, layer_stream);
  }
  }

  int Start(const char* stream_id, bool enable) {
    xcast_data data;
    data["enabled"] = enable;
    int32_t ret = xcast_core::set_property(XC_STREAM_ENABLED, "wemeet-channel", stream_id, data);
    if (strcmp(stream_id, "video-out") == 0) {
      xcast_data newcam_name(xcast_core::get_property(XC_CAMERA_DEFAULT));
      xcast_core::set_property(XC_STREAM_CAPTURE, "wemeet-channel","video-out", newcam_name);
    }
    return ret;
  }

  int Request(const char* stream_id, bool enable, bool is_small) {
    xcast_data data;
    data["enabled"] = enable;
    if (is_small) {
      data["size"] = "small";
    }
    int32_t ret = xcast_core::set_property(XC_STREAM_ENABLED, "wemeet-channel", stream_id, data);
    return ret;
  }
  
  int SwitchSource(const char* device_id) {
    xcast_data device_name(device_id);
    int ret = xcast_core::set_property(XC_STREAM_CAPTURE, "wemeet-channel", "video-out", device_name);
    return ret;
  }

  int GetState(const char* stream_id) {
    xcast_data state = xcast_core::get_property(XC_STREAM_STATE, "wemeet-channel", stream_id);
    return state.int32_val();
  }
}
}
  


